#ifndef INCLUDED_ParameterList
#define INCLUDED_ParameterList
/*
 * This parameter file is modeifed from SOCS system.
 */
#include "ParseReadsOpts.h"
#include "Flags.h"
#include "ShortReadUtil.h"
#include "ReadsFileParser.h"
#include "stdafx.h"
#include <string>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <limits>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
// Use OpenMP is gcc version is later than 4.2
#ifdef __GNUC__
#ifdef __GNUC_PATCHLEVEL__
#define __GNUC_VERSION__ (__GNUC__ * 10000 \
                            + __GNUC_MINOR__ * 100 \
                            + __GNUC_PATCHLEVEL__)
#else
#define __GNUC_VERSION__ (__GNUC__ * 10000 \
                            + __GNUC_MINOR__ * 100)
# endif

#if __GNUC_VERSION__ >= 40200
#include <omp.h>
#endif
#else
#ifdef _MSC_VER
#if _MSC_VER >= 2000
#include <omp.h>
#endif
#endif
#endif
using namespace std;

class MappingOpts : public CParseReadsOpts, public BuildTableOpts
{
public:
    MappingOpts(void);
    virtual ~MappingOpts(void);
    void setDefaults(void);
    void clearOutputFileName(bool clear = true);
    unsigned int readLength;
    unsigned int readLength2;
    string fullCommand;
    // I/O options
    bool bPrintSamHeader;             // Default is true
    bool bIgnoreQS;                   // Default is false
    bool bPrintNM;                    // Default is false
    bool bPrintNH;                    // Default is false
    bool bPrintAlignments;            // Default is false
    bool bPrintAmbigReadsSeparately;  // Default is false
    bool bPrintUnMappedReads;         // Default is false
    bool bExcludeAmbiguousReads;      // Default is true
    bool bPrintAmbiguousReadsOnly;    // Default is false
    bool bPrintBadReads;              // Default is false
    bool bPrintFirstAlignmentOnly;    // Default is false
    bool bGetAllAlignments;           // Default is false
    bool bMap2ForwardStrandOnly;      // Default is false
    bool bMap2ReverseStrandOnly;      // Default is false
    bool bPrintAmbigReadsInOneLine;   // Default is false
    char logFileN[FILENAME_MAX];
    char outputDir[FILENAME_MAX];
    char outputFileN[FILENAME_MAX];
    char outputFormat[FILENAME_MAX];
    char badReadFileN[FILENAME_MAX];
    char ambiguousReadFileN[FILENAME_MAX];
    char unmappedFileN[FILENAME_MAX];
    char readsFileFormat[FILENAME_MAX];
    int ambiguousDiffThreshold;
    int mismatchScoreThreshold;
    int maxAlignPerRead;
    int subDiffThreshold;
    int subDiffThreshold2;

    bool bExcludeAmbiguousPaired;
    bool bPrintBestPaired;
    bool bPrintRef4PairedInMapping;
    bool bPrintPairedRQ;
    bool bZipOutput;
    // The default is output all combinations paired end mappings
    bool frOnly; // Paired end can only align to different strand.
    bool ffOnly; // Paired end can only align to the same strand.
    int disLB; // distance lower bound
    int disUB; // distance upper bound
    unsigned int truncatedReadPrefix;
    char readtag_delimiter;
    unsigned int maxThreadNum; // for OpenMp
};

class ParameterList : public MappingOpts
{
public:
    ParameterList(void) ;
    void setDefaults(void);
    bool checkRefValidity(void);
    bool truncatReadLength(void);
    void getOptsByCheckingExtName(void);
    void printSetting(void);

    bool validFlag;
    // Basic Input
    char refFile[FILENAME_MAX];
    char indexFileN[FILENAME_MAX];
    char indexFileN2[FILENAME_MAX];
    char seedName[FILENAME_MAX];
    char seedName2[FILENAME_MAX]; // For the paired-end
    string refFormat; // index, fasta, list
    // Index
    bool bMakeIndex;  // Default is false
    bool bSaveIndex;  // Default is false
    // For Pairend Read
    bool bMatePairedReads;
    char matePairFileN1[FILENAME_MAX];
    char matePairFileN2[FILENAME_MAX];
    // others
    bool bMaskedMathRepeat;
private:
    bool isReadLengthValid(void);
    bool truncatReadLength4LongShortPairedRead(void);
};

bool printOptWarning4SingleEndOpts(ParameterList &P);
bool printOptWarning4PairedEndOpts(ParameterList &P);

ParameterList getParameterList(int argc, const char** argv);
bool retriveReadSetsAndSettings(ParameterList& P, \
                                vector<string>& readSetsList1,\
                                vector<string>& readSetsList2);
bool checkReadsSetNamesValidity(vector<string>& readSetsList1,\
                                vector<string>& readSetsList2);
unsigned int getReadLength(const char* readSetFileName, char expFileFormat = 'N');
bool getReadSetsFilenames(ParameterList &P,\
                          vector<string>& readSetList1,\
                          vector<string>& readSetList2);
bool checkFileListIsForPairedReads(const char* readSetListFilename);
bool checkFileListHasTheRightExt(vector<string>& readSetList);
bool withSupportExtFileName(const char* fileName);
bool withFastaExtFileName(const char* fileName);
void selectSeed(ParameterList& P);
void printSynopsis(void);
void printUsageInfo(string helpOpt);

// Overwrite string if the source string is not null
inline bool setStr(char* str1, const char* str2)
{
    if (str2[0] != '\0') {
        strcpy(str1, str2);
        return(true);
    } else {
        return(false);
    }
}

inline bool isReadShort(unsigned int readLength)
{
    return(readLength <= MAX_READ_LENGTH);
}

inline bool isReadProperLong(unsigned int readLength)
{
    return(readLength > MAX_READ_LENGTH &&  readLength <= MAX_LONG_READ_LENGTH);
}

inline bool isReadTooLong(unsigned int readLength)
{
    return(readLength > MAX_LONG_READ_LENGTH);
}

inline bool isReadTooShort(unsigned int readLength)
{
    return(readLength < MIN_READ_LENGTH);
}
#endif

